#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2023/12/3 13:11
# @Author  : 新猿异码
# @Site    : https://gitee.com/chshao/autotest
# @CSDN    : https://blog.csdn.net/m0_37576542?type=blog
# @File    : AutoLogger.py
# @Desc    : 模块功能描述
# @Software: PyCharm
import os
import sys
import logging
import traceback

try:
    from colorlog import StreamHandler
    from colorlog import ColoredFormatter as StreamFormatter
except ImportError:
    print("\033[0;31mif you want to use colorlog, please install by 'pip install colorlog'\033[0m")
    StreamHandler = logging.StreamHandler
    StreamFormatter = logging.Formatter


def singleton(cls):
    _instance = {}

    def _singleton(*args, **kwargs):
        if cls not in _instance:
            _instance[cls] = cls(*args, **kwargs)
        return _instance[cls]

    return _singleton


@singleton
class AutoLogger(object):
    PROJECT_HANDLER = 'projectHandler'
    CONSOLE_HANDLER = 'consoleHandler'
    CASE_HANDLER = 'caseHandler'
    DEFAULT_FMT = '[%(asctime)s][PID-%(process)s][%(levelname)s] %(message)s'
    DEFAULT_FMT_COLOR = '%(log_color)s[%(asctime)s][PID-%(process)s][%(levelname)s] %(message)s'

    def __init__(self):
        self.__logger = logging.getLogger(__name__)
        self.__logger.setLevel(logging.DEBUG)
        # 添加控制台日志
        self.addStreamHandler(self.CONSOLE_HANDLER, logging.DEBUG)

    def addStreamHandler(self, handlerName, level):
        # 创建控制台输出handler
        fmt_str = self.DEFAULT_FMT if StreamFormatter.__name__ == "Formatter" else self.DEFAULT_FMT_COLOR
        ch = StreamHandler(sys.stdout) if StreamFormatter.__name__ == "Formatter" else StreamHandler()
        ch.setLevel(level)
        ch.name = handlerName
        ch.setFormatter(StreamFormatter(fmt_str))
        self.__logger.addHandler(ch)

    def addFileHandler(self, filePath, handlerName, level):
        fh = logging.FileHandler(filePath, encoding='utf-8')
        fh.name = handlerName
        fh.setLevel(level)
        formatter = logging.Formatter(self.DEFAULT_FMT)
        fh.setFormatter(formatter)
        self.__logger.addHandler(fh)

    def beginProjectLog(self, projectLogPath, level):
        if not os.path.exists(projectLogPath):
            os.makedirs(projectLogPath)
        projectLogFileAbs = os.path.join(projectLogPath, 'test_run_detail.log')
        self.addFileHandler(projectLogFileAbs, self.PROJECT_HANDLER, level)

    def beginCaseLog(self, caseLogPath, caseName, level):
        logPath = os.path.join(caseLogPath, caseName)
        if not os.path.exists(logPath):
            os.makedirs(logPath)
        caseLogFileAbs = os.path.join(logPath, caseName + '.log')
        self.addFileHandler(caseLogFileAbs, self.CASE_HANDLER, level)

    def endCaseLog(self):
        self.removeCaseHandler()

    def endProjectLog(self):
        try:
            logging.shutdown()
        except:
            pass

    def removeCaseHandler(self):
        for handler in self.__logger.handlers:
            if handler.name.startswith('case'):
                try:
                    handler.flush()
                    handler.close()
                finally:
                    self.__logger.removeHandler(handler)

    def debug(self, msg: str):
        self.__logger.debug(msg)

    def info(self, msg: str):
        self.__logger.info(msg)

    def warn(self, msg: str):
        self.__logger.warning(msg)

    def error(self, msg: str):
        self.__logger.error(msg)

    def critical(self, msg: str):
        self.__logger.critical(msg)

    def traceback(self, msg: str = ''):
        self.__logger.error("{}, {}".format("".join(traceback.format_exception(*sys.exc_info())), msg))
